import cn.hutool.core.collection.CollUtil;
import com.mdxq.mall.product.ProductApp;
import com.mdxq.mall.product.entity.Brand;
import com.mdxq.mall.product.mapper.BrandMapper;
import com.mdxq.mall.product.mapper.ProductMapper;
import com.mybatisflex.core.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.*;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

@Slf4j
@SpringBootTest(classes = ProductApp.class)
public class RedisTemplateDemo {
    @Autowired
    RedisTemplate redisTemplate;

    @Autowired
    BrandMapper brandMapper;
    //将一个品牌对象缓存到redis
    @Test
    public void t1(){
        Brand brand = brandMapper.selectOneById(3);
        ValueOperations<String,Brand> operations = redisTemplate.opsForValue();
        operations.set("brand:3",brand);//序列化为二进制格式
        redisTemplate.expire("brand:3",5,TimeUnit.MINUTES);
        log.info("操作成功");
    }
    @Test
    public void t2(){
        ValueOperations<String,Brand> operations = redisTemplate.opsForValue();
        Brand brand = operations.get("brand:3");//查询到的结果反序列化成Java实例
        log.info("查询到品牌信息：{}",brand);
    }
    @Test
    public void t3(){
        //从MySQL里查询全部的品牌列表，然后保存到redis里
        List<Brand> brandList = brandMapper.selectAll();
        //返回一个可以操作的list类型数据
        ListOperations<String,Brand> listOperations = redisTemplate.opsForList();
        String key = "allBrandList";
        if (redisTemplate.hasKey(key)){
            redisTemplate.delete(key);//如果有key就删除
        }
        //将整个品牌列表全部push到列表里
        long llen = listOperations.rightPushAll(key,brandList);
        if (llen > 0){
            log.info("品牌列表已经缓存");
        }
    }
    @Test //list
    public void t4(){
        //先去缓存中查找数据，找到了就输出，未找到就查询mysql数据库，然后放入缓存中
        ListOperations<String,Brand> listOperations = redisTemplate.opsForList();
        List<Brand> brandList = null;
        String key = "allBrandList";
        if (redisTemplate.hasKey(key)){
            brandList = listOperations.range(key,0,-1);//查询数据结果
            log.info("redis");
        }else {
            brandList = brandMapper.selectAll();
            log.info("从mysql数据库中获取品牌列表");
            listOperations.rightPushAll(key,brandList);
        }
        if (CollUtil.isNotEmpty(brandList)){
            brandList.forEach(System.out::println);
        }
    }
    @Test  //set
    public void t5(){
        SetOperations<String,String> setOperations = redisTemplate.opsForSet();
        String k1 = "fruitSet1",k2 = "fruitSet2";
        setOperations.add(k1,"苹果","橘子","鸭梨");
        setOperations.add(k2,"橘子","香蕉","葡萄","樱桃");
        //分别计算两个果篮的交并差集
        log.info("交集");
        setOperations.intersect(k1,k2).forEach(System.out::println);
        log.info("并集");
        setOperations.union(k1,k2).forEach(System.out::println);
        log.info("差集");
        setOperations.difference(k1,k2).forEach(System.out::println);
    }
    @Test  //zset
    public void t6(){
        ZSetOperations<String,String> zSetOperations = redisTemplate.opsForZSet();
        String key = "当日蔬菜水果的价格_ZSet";
        zSetOperations.add(key,"a苹果",5.99);
        zSetOperations.add(key,"香蕉",4.99);
        zSetOperations.add(key,"葡萄",10.99);
        zSetOperations.add(key,"柑橘",3.99);
        zSetOperations.add(key,"鸭梨",15.99);
        zSetOperations.add(key,"草莓",5.69);
        Set<String> members = zSetOperations.range(key,0,-1);
//        Set<ZSetOperations.TypedTuple<String>> tupleSet = zSetOperations.rangeWithScores(key,0,-1);//低到高
//        Set<ZSetOperations.TypedTuple<String>> tupleSet = zSetOperations.reverseRangeWithScores(key,0,-1);//高到低
        Set<ZSetOperations.TypedTuple<String>> tupleSet = zSetOperations.reverseRangeByScoreWithScores(key,5.0,100,0,-1);//高到低+区间(5~100)
        tupleSet.forEach(tuple ->{
            log.info("水果：{} ，价格：{}",tuple.getValue(),tuple.getScore());
        });
    }
    @Autowired
    ProductMapper productMapper;
    @Test  //hash:保存一个对象（一条数据库记录）的部分数据，或者多表查询的数据结果
    public void t7(){
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.select("id","name","product_sn","price","brand_name");
        queryWrapper.eq("id",38);
        //返回38号商品的信息
        Map<String,Object> productInfo = productMapper.selectOneByQueryAs(queryWrapper, HashMap.class);
        BigDecimal priceDecimal = (BigDecimal) productInfo.get("price");
        productInfo.remove("price");
        productInfo.put("price",priceDecimal.floatValue());//保存数据前先将价格格式改为float,默认bigdecimal
        //三个泛型分别是redis的key，field，value
        HashOperations<String,String,Object> hashOperations = redisTemplate.opsForHash();
        String key = "product:38";
        redisTemplate.delete(key);
        hashOperations.putAll(key,productInfo);
        log.info("成功，保存至redis");
    }
    @Test
    public void t8(){
        HashOperations<String,String,Object>  hashOperations = redisTemplate.opsForHash();
        String key = "product:38";
        float oldPrice = (float)hashOperations.get(key,"price");
        float newPrice = oldPrice+100f;
        log.info("加价前{}",hashOperations.get(key,"price"));
        hashOperations.put(key,"price",newPrice);
        log.info("加价后{}",hashOperations.get(key,"price"));
        log.info("{}个键值对",hashOperations.size(key));
        Map<String,Object> productInfo = hashOperations.entries(key);
        productInfo.forEach((k,v)->{
            log.info("field:{} , value:{}",k,v);
        });

    }
}
